package io.traveller.apiGateway.server;

import com.netflix.zuul.context.ContextLifecycleFilter;
import com.netflix.zuul.filters.FilterRegistry;
import com.netflix.zuul.http.ZuulServlet;
import com.netflix.zuul.monitoring.MonitoringHelper;
import io.traveller.apiGateway.client.EnableRouteServer;
import io.traveller.apiGateway.client.discovery.DiscoveryClientRouteExtLocator;
import io.traveller.apiGateway.server.filter.pre.PreAuthFilter;
import io.traveller.apiGateway.server.filter.pre.PreGetAccessTokenFilter;
import io.traveller.apiGateway.server.filter.pre.PreGetRouteExtFilter;
import io.traveller.apiGateway.server.filter.pre.PreRequestHeaderFilter;
import io.traveller.auth.api.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;

/**
 * API Gateway应用
 * <p>
 * Created by yunai on 16/9/10.
 */
@EnableZuulProxy
@SpringBootApplication
@EnableRouteServer
@ImportResource("classpath:/spring/application-context-dubbo.xml")
public class Application {

    @Autowired
    private DiscoveryClientRouteExtLocator routeExtLocator;
    @Autowired
    private ServletRegistrationBean zuulServlet;

    @Autowired(required = false)
    @SuppressWarnings("SpringJavaAutowiringInspection")
    private AuthService authService;

    /**
     * ZuulServlet
     *
     * @return ZuulServlet
     */
    @Bean
    protected ServletRegistrationBean zuulServlet() {
        return new ServletRegistrationBean(new ZuulServlet(), "/*");
    }

    /**
     * 请求Context清理
     *
     * @return ContextLifecycleFilter
     */
    @Bean
    protected FilterRegistrationBean zuulContextLifecycleFilter() {
        return new FilterRegistrationBean(new ContextLifecycleFilter(), zuulServlet);
    }

    @Bean
    protected PreRequestHeaderFilter preRequestHeaderFilter() {
        return new PreRequestHeaderFilter();
    }

    @Bean
    protected PreGetRouteExtFilter preGetRouteExtFilter() {
        return new PreGetRouteExtFilter(routeExtLocator);
    }

    @Bean
    protected PreGetAccessTokenFilter preGetAccessTokenFilter() {
        return new PreGetAccessTokenFilter(authService);
    }

    @Bean
    protected PreAuthFilter preAuthFilter() {
        return new PreAuthFilter(authService);
    }

    @Bean
    protected ApplicationRunner zuulFilterInitRunner() {
        return new ApplicationRunner() {

            @Autowired
            private PreRequestHeaderFilter preRequestHeaderFilter;
            @Autowired
            private PreGetRouteExtFilter preGetRouteExtFilter;
            @Autowired
            private PreGetAccessTokenFilter preGetAccessTokenFilter;
            @Autowired
            private PreAuthFilter preAuthFilter;

            @Override
            public void run(ApplicationArguments applicationArguments) throws Exception {
                // 监控模块
                MonitoringHelper.initMocks();
                // 初始化Filter
                final FilterRegistry r = FilterRegistry.instance();
                r.put(preRequestHeaderFilter.getClass().getName(), preRequestHeaderFilter);
                r.put(preGetRouteExtFilter.getClass().getName(), preGetRouteExtFilter);
                r.put(preGetAccessTokenFilter.getClass().getName(), preGetAccessTokenFilter);
                r.put(preAuthFilter.getClass().getName(), preAuthFilter);
            }
        };
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}